home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Documentation / Tech Notes & Articles / Recipes / Imaging & Layout / Clipping Embedded Facets < prev    next >
Encoding:
Text File  |  1995-07-10  |  6.8 KB  |  129 lines  |  [TEXT/ttxt]

  1. OpenDoc™ Recipes
  2.  
  3. Clipping Embedded Facets
  4. by The OpenDoc Design Team
  5. April 18, 1985
  6.  
  7.  
  8. © 1993-1995  Apple Computer, Inc. All Rights Reserved.
  9. Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
  10. Mac and OpenDoc are trademarks of Apple Computer, Inc.
  11.  
  12.  
  13. Embedding and Clipping
  14.  
  15. Containing parts manage the clipping of their embedded parts.  Containing parts use the ClipShape of embedded facets to indicate how embedded parts should clip their drawing operations. A facet's ClipShape indicates which portion of the facet is visible within its containing facet. If the containing facet is itself obscured, that does not affect the embedded facet's ClipShape. To find out what portion of a facet is visible on its canvas, use ODFacet::GetAggregateClipShape.
  16.  
  17. At the risk of sounding tautalogical, a containing part needs to update its embedded facets' ClipShapes whenever the way they are clipped changes. There are a number of cases where that may happen:  when content is rearranged or reformatted, when an embedded part is resized, when the active border shape moves from one frame to another, when selection handles are shown or hidden, when an embedded frame's UsedShape is changed. If the containing part does not allow embedded frames to be overlapped (like a text part), the number of situations requiring clipping will be minimal. If a containing part allows complex, overlapping arrangement of embedded frames, like a drawing or presentation part, then there will be many situations that require clipping.
  18.  
  19. Responsibilities
  20.  
  21. Containing Part
  22.  
  23. • Manage the ClipShape of embedded facets. Ensure embedded parts don't overwrite other parts, the containing part's intrinsic content, or the active border shape.
  24. • Display in the portion of an embedded frame not included in the frame's UsedShape. The embedded part had guaranteed that it won't draw outside it's display frame's UsedShape, so the containing part has to do it.
  25.  
  26. Embedded Part
  27.  
  28. • Clip drawing operations to display facet's AggregateClipShape or WindowAggregateClipShape.
  29. • Never draw outside of display frame's UsedShape (except root parts).
  30. • If displaying asynchronously, update clipping when GeometryChanged notification indicates that the ClipShape has changed.
  31.  
  32. About the Sample Code
  33.  
  34. The code below follows a very simple recipe for clipping embedded facets. More sophisticated techniques are possible, and may be required for advanced imaging features such as translucency or compositing.
  35.  
  36. The basic recipe for clipping an embedded facet:
  37. • Start with its FrameShape.
  38. • Subtract from that the shapes of all the other facets and intrinsic content within the containing part that obscure the frame.
  39.  
  40. Some tips:
  41. • When a facet is obscured by another facet, use the UsedShape of the obscuring facet's frame to clip the facet.
  42. • Make sure that ALL intrinsic content is accounted for. This includes selection handles, active frame borders, frame adornments, etc. Anything that isn't an embedded frame but you don't want overwritten by an asynchronously displaying part (such as a clock or movie) must be included. 
  43. • If a containing part receives a UsedShapeChanged notification, you only need to re-clip the facets behind the changed one. That recipe is the same as the one below, but just start at the changed facet, not at the uppermost one. Same thing if the active border changes - just re-clip the facets behind the facet of the active frame (or the previously active frame).
  44.  
  45. CMyPart::GetFacetForEmbeddedContentItem()
  46. Given a content object in the containing part, this method returns the embedded facet that needs to be clipped. If the containing part only allows one facet per embedded frame in each of its display frames, it doesn't need to store a pointer to the facet in the content object. In fact, that would be fairly confusing, and would just end up paralleling the facet list in the frame. Instead, this method will compute the intersection of the set of the immediate children of the containing part's display facet, and the set of the facets of the embedded frame. In that case, the intersection should be a single frame.
  47.  
  48. If a containing part allows multiple facets on an embedded frame in its content, it will need to keep an explicit reference to a facet in the content object. In that case, this method can just return that reference.
  49.  
  50. Sample Code
  51.  
  52. #include "Facet.xh"
  53. #include "FacetItr.xh"
  54. #include "Frame.xh"
  55. #include "Shape.xh"
  56. #include "Trnsform.xh"
  57. #include "FocusLib.h"
  58.  
  59. ...
  60.  
  61. void CMyPart::ClipEmbeddedFacets(Environment* ev, ODFacet* facet)
  62. {
  63.     ODCanvas* biasCanvas = facet->GetCanvas(ev);
  64.     ODGeometryMode geoMode = GetCanvasGeometryMode(ev, facet->GetCanvas(ev));
  65.     ODShape* workingClip = ODCopyAndRelease(ev, facet->AcquireClipShape(ev, biasCanvas));
  66.     workingClip->SetGeometryMode(ev,geoMode);
  67.     
  68.     // if an embedded frame is active, the active border should obscure
  69.     // other embedded frames.  border was recorded in ::AdjustActiveBorder()
  70.     if ( fActiveBorderShape != kODNULL )
  71.         workingClip->Subtract(ev, fActiveBorderShape);
  72.  
  73.     ODFacet* embFacet = kODNULL;    
  74.  ODFrame* embFrame = kODNULL;
  75.     ODShape* newClipShape = kODNULL;    
  76.     ODShape* newMaskShape = kODNULL;    
  77.     ODTransform* clipTrans = kODNULL;
  78.     
  79.     // compute clipping by iterating all content, intrinsic and embedded
  80.     ContentIterator* contents = this->CreateContentIterator(kODFrontToBack);
  81.     for ( item = contents->First(); contents->IsNotComplete(); item = contents->Next() )
  82.     {
  83.         if ( item->IsIntrinsic() )
  84.         {
  85.             // clip intrinsic content here if you need to
  86.             // ...
  87.             
  88.             // intrinsic content should obscure underlying frames
  89.             // GetMaskShape() also includes selection handles if item is selected
  90.             workingClip->Subtract(ev, item->GetMaskShape());
  91.         }
  92.         else
  93.         {
  94.             embFacet = this->GetFacetForEmbeddedContentItem(facet, item);
  95.    embFrame = embFacet->AcquireFrame(ev);
  96.             
  97.             // start with facet's FrameShape
  98.             newClipShape = ODCopyAndRelease(ev, embFrame->AcquireFrameShape(ev, biasCanvas));
  99.             newClipShape->SetGeometryMode(ev,geoMode);
  100.             // get UsedShape to obscure underlying facets
  101.             newMaskShape = ODCopyAndRelease(ev, embFrame->AcquireUsedShape(ev, biasCanvas));
  102.             
  103.             clipTrans = embFacet->AcquireExternalTransform(ev, biasCanvas);
  104.     
  105.             newClipShape->Transform(ev, clipTrans);                // now in containing frame coordinates
  106.             newClipShape->Intersect(ev, workingClip);
  107.             newClipShape->InverseTransform(ev, clipTrans);        // now in embedded frame coordinates
  108.             embFacet->ChangeGeometry(ev, newClipShape, kODNULL, biasCanvas);
  109.     
  110.             newMaskShape->Transform(ev, wclipTrans);            // now in containing frame coordinates
  111.             workingClip->Subtract(ev, newMaskShape);
  112.     
  113.    embFrame->Release(ev);
  114.             newClipShape->Release(ev);
  115.             newMaskShape->Release(ev);
  116.             clipTrans->Release(ev);
  117.         }
  118.     }
  119.     delete contents;
  120.     
  121.     workingClip->Release(ev);
  122. }
  123.  
  124. ODFacet* CMyPart::GetFacetForEmbeddedContentItem(ODFacet* facet, ContentItem* embeddedItem)
  125. {
  126.     // find the facet that is facet of "embeddedFrame" and contained by "facet"
  127. }
  128.  
  129.